import { InfoCircleFilled } from '@ant-design/icons'
import { Button, message, Space } from 'antd'
import modal from 'antd/es/modal'
import cs from 'classnames'
import MD5 from 'crypto-js/md5'
import dayjs from 'dayjs'
import { forwardRef, useContext, useEffect, useImperativeHandle, useRef, useState } from 'react'
import { CSSTransition } from 'react-transition-group'

import { Ocr } from '@/api'
import { GlobalContext } from '@/context'
import { get } from '@/utils/storage'
import useLocale from '@/utils/useLocale'

import locale from './locale'
import styles from './style//index.module.less'
type File = { path: string; name: string }[]

const OCRIdCard = ({ onData }: { onData?: (file: File) => void }, ref) => {
  const [show, setShow] = useState<boolean>(false)

  //打开时先进行鉴权
  const open = async () => {
    //无网络退出
    if (!network.current) {
      message.open({
        key: 'update-networkStatus',
        type: 'error',
        content: networkError(),
        duration: 3,
      })
      close()
      return
    }
    const permissions = await window.electron?.ipcRenderer.permissions('camera')
    if (permissions) {
      await getUserMedias()
      setShow(true)
      return
    }
    modal.confirm({
      title: t['setting.title'],
      icon: <InfoCircleFilled style={{ color: '#44C5E4' }} />,
      className: cs(styles['custom-modal'], lang === 'en-US' ? '' : styles['custom-modal-rtl']),
      closable: true,
      content: t['setting.content'],
      okText: t['setting.ok'],
      cancelText: t['cancel'],
      keyboard: false,
      centered: true,
      width: 425,
      onOk() {
        window.electron?.ipcRenderer.openSetting('camera')
      },
    })
  }

  const close = () => {
    if (timer.current) {
      clearTimeout(timer.current)
    }
    releaseUserMedia()
    setShow(false)
  }
  useImperativeHandle(ref, () => ({
    open: open,
  }))

  const t = useLocale(locale)
  const videoRef = useRef(null)
  //获取所有设备
  const videoDevices = useRef([])

  const getUserMedias = async () => {
    console.log('获取媒体设备')
    // 获取摄像头设备
    await navigator.mediaDevices
      .enumerateDevices()
      .then(async function (devices) {
        videoDevices.current = devices.filter((device) => device.kind === 'videoinput')
      })
      .catch(function (err) {
        console.log(err)
      })
  }

  const [deviceId, setDeviceId] = useState<string>('')
  const mediaStream = useRef<any>() // 定义一个变量用于保存获取到的摄像头流
  const getUserMedia = () => {
    // 获取摄像头设备
    if (videoDevices.current.length > 0) {
      // 选择后置摄像头
      const backCamera = videoDevices.current[videoDevices.current.length - 1]
      // 如果找到前置摄像头，则使用该设备
      // 否则，使用第一个摄像头设备
      const selectedCamera = backCamera || videoDevices.current[0]
      getStream(selectedCamera)
    } else {
      console.log('No video devices found')
    }
  }

  const getStream = (selectedCamera) => {
    setDeviceId(selectedCamera.deviceId)
    // 使用摄像头设备
    navigator.mediaDevices
      .getUserMedia({
        video: {
          deviceId: selectedCamera.deviceId,
          width: { ideal: 592 },
          height: { ideal: 362 },
          frameRate: { ideal: 30 }, // 设置帧率为30帧每秒
        },
      })
      .then(function (stream) {
        mediaStream.current = stream
        videoRef.current.srcObject = stream
        videoRef.current.play()
        OCR()
      })
      .catch(function (err) {
        console.log(err)
      })
  }

  //关闭释放摄像头
  const releaseUserMedia = async () => {
    console.log('关闭释放摄像头')
    if (mediaStream.current) {
      const tracks = mediaStream.current.getTracks()
      tracks &&
        tracks.forEach(async (track) => {
          await track.stop()
        })
      mediaStream.current = null
    }
  }

  const { lang } = useContext(GlobalContext)

  const network = useRef<boolean>(true)
  const networkError = () => {
    if (lang === 'ar-EG') {
      return 'تم قطع شبكة '
    } else {
      return `Network disconnected`
    }
  }

  const updateOnlineStatus = () => {
    network.current = navigator.onLine
    console.log('外网环境', navigator.onLine)
  }

  useEffect(() => {
    updateOnlineStatus()
    window.addEventListener('online', updateOnlineStatus)
    window.addEventListener('offline', updateOnlineStatus)
    return () => {
      releaseUserMedia()
      window.removeEventListener('online', updateOnlineStatus)
      window.removeEventListener('offline', updateOnlineStatus)
      if (timer.current) {
        clearTimeout(timer.current)
      }
    }
  }, [])

  useEffect(() => {
    if (show) {
      getUserMedia()
    }
  }, [show])

  const [cw, setCw] = useState<number>(592)
  const [ch, setCh] = useState<number>(362)
  const contentRef = useRef(null)
  const timer = useRef<any>()

  const OCR = async () => {
    //无网络退出
    if (!network.current) {
      message.open({
        key: 'update-networkStatus',
        type: 'error',
        content: networkError(),
        duration: 3,
      })
      close()
      return
    }
    try {
      const { base64, file } = take()
      const timestamp = dayjs().valueOf().toString()
      const token = get('token')
      const ticket = MD5(base64 + timestamp + token)
      const formData = new FormData()
      formData.append('file', file)
      formData.append('ticket', ticket)
      formData.append('timestamp', timestamp)

      const { data } = await Ocr(formData)
      try {
        onData(data)
      } catch (error) {
        // 处理 onData 函数的错误
        console.error('onData error:', error)
      }
      close()
    } catch (error) {
      //超时处理，网络上不可信的
      if (error?.message?.includes('timeout')) {
        message.open({
          key: 'update-networkStatus',
          type: 'error',
          content: networkError(),
          duration: 3,
        })
        close()
        return
      }
      if (timer.current) {
        clearTimeout(timer.current)
      }
      timer.current = setTimeout(() => {
        OCR()
      }, 1500)
    }
  }

  //截图
  const take = () => {
    const canvas = document.createElement('canvas')
    const context = canvas.getContext('2d')
    const width = videoRef.current.videoWidth
    const height = videoRef.current.videoHeight
    canvas.width = width
    canvas.height = height
    const x = (canvas.width - width) / 2
    const y = (canvas.height - height) / 2
    context.drawImage(
      videoRef.current,
      0,
      0,
      videoRef.current.videoWidth,
      videoRef.current.videoHeight,
      x,
      y,
      width,
      height
    )
    const data = canvas.toDataURL('image/png')
    const base64Regex = /^data:[\w\/\+-]+;base64,/
    if (base64Regex.test(data)) {
      // 解析Base64编码，获取文件类型和二进制数据
      const matches = data.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/)
      const fileMimeType = matches[1]
      const fileData = matches[2]
      // 将Base64编码的文件转换为二进制数据
      const byteArray = Uint8Array.from(atob(fileData), (c) => c.charCodeAt(0))
      // 创建文件对象
      const file = new File([byteArray], 'filename.png', { type: fileMimeType })
      return { base64: fileData, file }
    }
    throw new Error('No data')
  }

  const switchCamera = () => {
    if (timer.current) {
      clearTimeout(timer.current)
    }
    releaseUserMedia()
    const index =
      videoDevices.current.findIndex(function (device) {
        return device.deviceId === deviceId
      }) + 1
    const selectedCamera = videoDevices.current[index % videoDevices.current.length]
    getStream(selectedCamera)
  }

  return (
    <CSSTransition in={show} classNames={'fade'} timeout={300} unmountOnExit>
      <div className={styles['camera']}>
        <div className={styles['content']} ref={contentRef}>
          <div className={styles['info']}>
            <div className={styles['tips']}>{t['tipText']}</div>
            <div className={styles['videoBg']} style={{ width: cw, height: ch }}>
              <div className={styles['angle1']}></div>
              <div className={styles['angle2']}></div>
              <div className={styles['angle3']}></div>
              <div className={styles['angle4']}></div>
              <video
                ref={videoRef}
                className={styles['video']}
                style={{ width: cw, height: ch }}
              ></video>
            </div>
          </div>

          <Space className={styles['action']} size={20}>
            {/* <>
              <Button
                type="primary"
                ghost
                shape="round"
                className={styles['button']}
                onClick={switchCamera}
              >
                {t['switch']}
              </Button>
            </> */}

            <>
              <Button
                type="primary"
                ghost
                shape="round"
                className={styles['button']}
                onClick={close}
              >
                {t['cancel']}
              </Button>
            </>
          </Space>
        </div>
      </div>
    </CSSTransition>
  )
}

export default forwardRef(OCRIdCard)
